home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AppsToGo / Kibitz / KibitzWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  16.7 KB  |  642 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        kibitzwindow.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __ERRORS__
  21. #include <Errors.h>
  22. #endif
  23.  
  24. #ifndef __FONTS__
  25. #include <Fonts.h>
  26. #endif
  27.  
  28. #ifndef __GWLAYERS__
  29. #include <GWLayers.h>
  30. #endif
  31.  
  32. #ifndef __RESOURCES__
  33. #include <Resources.h>
  34. #endif
  35.  
  36. #ifndef __TEXTEDITCONTROL__
  37. #include <TextEditControl.h>
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include <Utilities.h>
  46. #endif
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. extern short    gPrintPage;                    /* Non-zero means we are printing. */
  55. extern LayerObj    gBoardLayer;
  56. extern short    gClearSquare;
  57.  
  58. Boolean            gDescriptive;
  59. CIconHandle        gPieceCIcon[26];
  60.  
  61. static short        gLastPiece[120];
  62. static RgnHandle    gLastColorRgn;
  63.  
  64.  
  65.  
  66. /*****************************************************************************/
  67. /*****************************************************************************/
  68.  
  69. #ifdef applec
  70. #pragma segment KibitzWindow
  71. #endif
  72.  
  73. /*****************************************************************************/
  74. /*****************************************************************************/
  75.  
  76.  
  77.  
  78. /* This function adds the application's controls to a window. */
  79.  
  80. OSErr    AppNewWindowControls(FileRecHndl frHndl, WindowPtr window, WindowPtr behind)
  81. {
  82.     WindowPtr        oldPort;
  83.     OSErr            err;
  84.     TEHandle        mssgIn, mssgOut;
  85.     CTEDataHndl        teData;
  86.     ControlHandle    sendMssg, beepOnMove, beepOnMssg, viewCtl;
  87.     Rect            ctlRect, brdrRect, viewRect, destRect;
  88.     ControlHandle    gameSlider, whiteStarts, blackStarts, resign, draw;
  89.     ControlHandle    record, sendSnd;
  90.     Handle            textHndl;
  91.     Boolean            messageDoc;
  92.     short            mode;
  93.     TextStyle        styl;
  94.     Handle            finf;
  95.  
  96.     GetPort(&oldPort);
  97.     SetPort(window);
  98.  
  99.     SetRect(&ctlRect,
  100.             kBoardWidth + 20,
  101.             35,
  102.             rWindowWidth - 20,
  103.             kBoardHalfHeight + kBoardVOffset - 1
  104.     );
  105.  
  106.     brdrRect = viewRect = ctlRect;
  107.     InsetRect(&viewRect, 4, 4);
  108.     destRect = viewRect;
  109.     destRect.right -= 2;
  110.         /* This fixes a TextEdit problem where the view has to be a little
  111.         ** outside the dest on the right, or else characters are clipped.
  112.         */
  113.  
  114.     finf = GetResource('finf', 128);
  115.     styl.tsFont = (*(short **)finf)[1];
  116.     styl.tsSize = (*(short **)finf)[3];
  117.  
  118.     TextFont(styl.tsFont);
  119.     TextSize(styl.tsSize);
  120.  
  121.     CTENew(rTECtl,                /* viewCtl of resID for TextEdit control. */
  122.            true,                    /* Visible.                                  */
  123.            window,                    /* Window to hold TERecord.                  */
  124.            &mssgIn,                    /* Return handle for TERecord.               */
  125.            &ctlRect,                /* Rect for view control.                  */
  126.            &destRect,                /* destRect for TERecord                  */
  127.            &viewRect,                /* viewRect for TERecord                  */
  128.            &brdrRect,                /* Used to frame a border.                  */
  129.            32000,                    /* Maximum TextEdit document length.      */
  130.            cteReadOnly+cteVScroll    /* TERecord is regular read-only.          */
  131.     );
  132.     if (mssgIn)
  133.         TESetStyle((doFont | doSize), &styl, false, mssgIn);
  134.  
  135.     OffsetRect(&ctlRect, 0, kBoardHalfHeight - 38);
  136.  
  137.     messageDoc = false;
  138.     if ((*frHndl)->doc.myColor == kMessageDoc) messageDoc = true;
  139.     if (messageDoc)
  140.         SetRect(&ctlRect, -1, -1, rWindowWidth - 14, rWindowHeight + 1);
  141.             /* When the window is a message document, the whole window is the outbox.
  142.             ** This keep the actual differences between window kinds to a minimum,
  143.             ** while altering the appearance greatly. */
  144.  
  145.     brdrRect = viewRect = ctlRect;
  146.     InsetRect(&viewRect, 4, 4);
  147.     destRect = viewRect;
  148.     destRect.right -= 2;
  149.  
  150.     mode = cteVScroll;
  151.     if (behind == (WindowPtr)-1)
  152.         if (!(*frHndl)->doc.arrangeBoard)
  153.             mode |= cteActive;
  154.     CTENew(rTECtl, true, window, &mssgOut, &ctlRect, &destRect, &viewRect, &brdrRect, 32000, mode);
  155.  
  156.     if (mssgOut) {
  157.         TESetStyle((doFont | doSize), &styl, false, mssgOut);
  158.  
  159.         viewCtl = CTEViewFromTE(mssgOut);
  160.         teData  = (CTEDataHndl)(*viewCtl)->contrlData;
  161.         (*teData)->mode |= cteActive;
  162.             /* Make sure that when a window is activated, the caret blinks.  We need
  163.             ** to do this because the window isn't necessarily opened as the front window.
  164.             ** If we create the TextEdit Control as the active control for a window that
  165.             ** isn't opened as the front window, then we will turn off the caret for
  166.             ** whatever window is the front window.  Al we are doing here is determining
  167.             ** that the message-out TextEdit Control will be the active control when the
  168.             ** window is first brought to the front. */
  169.     
  170.         textHndl = (Handle)(*frHndl)->doc.legalMoves;
  171.         (*frHndl)->doc.legalMoves = (MoveListHndl)CTESwapText(mssgOut, textHndl, nil, false);
  172.             /* AppOpenDocument may have placed some text for the out-box TextEdit
  173.             ** control temporarily in the legalMoves handle.  Move this text into
  174.             ** the out-box TextEdit control. */
  175.     }
  176.  
  177.     sendMssg   = GetNewControl(rSendMessage, window);
  178.     if (sendMssg) HiliteControl(sendMssg, 255);
  179.     beepOnMove = GetNewControl(rMoveNotify, window);
  180.     if (beepOnMove)  HiliteControl(beepOnMove, 255);
  181.     beepOnMssg = GetNewControl(rMssgNotify, window);
  182.     if (beepOnMssg)  HiliteControl(beepOnMssg, 255);
  183.  
  184.     whiteStarts = GetNewControl(rWhiteStarts, window);
  185.     if (whiteStarts) {
  186.         OffsetControl(whiteStarts, -4096, 0);
  187.         SetControlValue(whiteStarts, (*frHndl)->doc.startColor ^ 1);
  188.         ShowControl(whiteStarts);
  189.     }
  190.     blackStarts = GetNewControl(rBlackStarts, window);
  191.     if (blackStarts) {
  192.         OffsetControl(blackStarts, -4096, 0);
  193.         SetControlValue(blackStarts, (*frHndl)->doc.startColor);
  194.         ShowControl(blackStarts);
  195.     }
  196.  
  197.     resign      = GetNewControl(rResign, window);
  198.     draw        = GetNewControl(rDraw, window);
  199.     record  = GetNewControl(rRecordSound, window);
  200.     if (record) HiliteControl(record, 255);
  201.     sendSnd = GetNewControl(rSendSound, window);
  202.     if (sendSnd)   HiliteControl(sendSnd, 255);
  203.  
  204.     gameSlider = BoardSliderNew(window);
  205.  
  206.     (*frHndl)->doc.message[kMessageIn]  = mssgIn;
  207.     (*frHndl)->doc.message[kMessageOut] = mssgOut;
  208.     (*frHndl)->doc.sendMessage = sendMssg;
  209.     (*frHndl)->doc.beepOnMove  = beepOnMove;
  210.     (*frHndl)->doc.beepOnMssg  = beepOnMssg;
  211.     (*frHndl)->doc.gameSlider  = gameSlider;
  212.     (*frHndl)->doc.wbStart[0]  = whiteStarts;
  213.     (*frHndl)->doc.wbStart[1]  = blackStarts;
  214.     (*frHndl)->doc.resign      = resign;
  215.     (*frHndl)->doc.draw        = draw;
  216.     (*frHndl)->doc.record      = record;
  217.     (*frHndl)->doc.sendSnd     = sendSnd;
  218.  
  219.     if (
  220.         (mssgIn) &&
  221.         (mssgOut) &&
  222.         (sendMssg) &&
  223.         (beepOnMove) &&
  224.         (beepOnMssg) &&
  225.         (gameSlider) &&
  226.         (whiteStarts) &&
  227.         (blackStarts) &&
  228.         (resign) &&
  229.         (draw) &&
  230.         (record) &&
  231.         (sendSnd)
  232.     ) {
  233.         if (messageDoc) {
  234.             CTEHide(mssgIn);
  235.             HideControl(sendMssg);
  236.             MoveControl(sendMssg, 0, -4096);    /* So no border is drawn. */
  237.             HideControl(beepOnMove);
  238.             HideControl(beepOnMssg);
  239.             HideControl(gameSlider);
  240.             HideControl(whiteStarts);
  241.             HideControl(blackStarts);
  242.             HideControl(resign);
  243.             HideControl(draw);
  244.             HideControl(record);
  245.             HideControl(sendSnd);
  246.         }
  247.         AdjustGameSlider(frHndl);
  248.         err = noErr;
  249.     }
  250.     else
  251.         err = memFullErr;
  252.  
  253.     SetPort(oldPort);
  254.     return(err);
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************/
  260.  
  261.  
  262.  
  263. void    DrawTime(FileRecHndl frHndl)
  264. {
  265.     WindowPtr        oldPort;
  266.     Rect            clockRect;
  267.     short            clock, i, time[3];
  268.     unsigned long    timeLeft, displayTime;
  269.     Str32            pstr, timestr;
  270.  
  271.     if ((*frHndl)->doc.arrangeBoard) return;
  272.  
  273.     oldPort = SetFilePort(frHndl);
  274.  
  275.     TextMode(srcCopy);
  276.     TextFont(systemFont);
  277.     TextSize(0);
  278.     TextFace(normal);
  279.  
  280.     for (clock = 0; clock < 2; ++clock) {
  281.  
  282.         clockRect = BoardRect();
  283.  
  284.         if (clock == (*frHndl)->doc.invertBoard)
  285.             clockRect.top += 14;
  286.  
  287.         clockRect.left   = clockRect.right + 26;
  288.         clockRect.right  = clockRect.left + 70;
  289.         clockRect.bottom = clockRect.top + 14;
  290.  
  291.         timeLeft = (*frHndl)->doc.timeLeft[clock];
  292.         if (timeLeft == -1) {
  293.             EraseRect(&clockRect);
  294.             continue;
  295.         }
  296.  
  297.         if ((displayTime = (*frHndl)->doc.displayTime[clock]) > timeLeft)
  298.              displayTime = (*frHndl)->doc.displayTime[clock]  = timeLeft;
  299.  
  300.         MoveTo(clockRect.left + 6, clockRect.top + 14);
  301.  
  302.         for (i = 3; i;) {
  303.             displayTime /= 60;
  304.             time[--i] = displayTime % 60;
  305.         }
  306.         timestr[0] = 0;
  307.         for (i = 0; i < 3; ++i) {
  308.             pcpydec(pstr, time[i]);
  309.             if (pstr[0] == 1) pcat(timestr, "\p0");
  310.             pcat(timestr, pstr);
  311.             pcat(timestr, (StringPtr)"\1:\1:\1 " + (i << 1));    /* Append colon or space. */
  312.         }
  313.         DrawString(timestr);
  314.     }
  315.  
  316.     TextMode(srcOr);
  317.     SetPort(oldPort);
  318. }
  319.  
  320.  
  321.  
  322. /*****************************************************************************/
  323.  
  324.  
  325.  
  326. void    ImageBoardLines(short increment, short hOffset, short vOffset)
  327. {
  328.     short    i;
  329.  
  330.     PenNormal();
  331.     PenSize(1, 1);
  332.  
  333.     for (i = 0; i <= 8; i += increment) {
  334.         MoveTo(hOffset, vOffset + kBoardSqSize * i);
  335.         Line(kBoardSqSize * 8, 0);
  336.         MoveTo(hOffset + kBoardSqSize * i, vOffset);
  337.         Line(0, kBoardSqSize * 8);
  338.     }
  339.  
  340.     PenNormal();
  341. }
  342.  
  343.  
  344.  
  345. /*****************************************************************************/
  346.  
  347.  
  348.  
  349. /* Image the document into the current port. */
  350.  
  351. void    ImageDocument(FileRecHndl frHndl, Boolean justBoard)
  352. {
  353.     short            r, c, rr, cc, piece, pieceIconID, fnum, i;
  354.     short            gameIndex, lastFrom, lastTo, square, ss, hOffset, vOffset;
  355.     Boolean            toWindow, invertBoard, messageDoc;
  356.     LayerObj        windowLayer;
  357.     Rect            sqRect, theInk, boardRect;
  358.     GameListHndl    gameMoves;
  359.     WindowPtr        curPort;
  360.     TEHandle        te;
  361.     Point            pt;
  362.     RgnHandle        colorRgn, testRgn;
  363.     static short    teOffset;
  364.  
  365.     GetPort(&curPort);
  366.  
  367.     toWindow = (curPort == (*frHndl)->fileState.window);
  368.     if (!toWindow) gClearSquare = 0;
  369.  
  370.     messageDoc = false;
  371.     if ((*frHndl)->doc.myColor == kMessageDoc) messageDoc = true;
  372.  
  373.     colorRgn = testRgn = nil;
  374.  
  375.     hOffset = kBoardHOffset;
  376.     vOffset = kBoardVOffset;
  377.     if (gPrintPage > 0) {
  378.         theInk = curPort->portRect;
  379.         GetFNum("\pTimes", &fnum);
  380.         TextFont(fnum);
  381.         TextSize(12);
  382.         TextFace(normal);
  383.         hOffset = theInk.right - 10 - kBoardWidth;
  384.         vOffset = 10;
  385.         if (messageDoc) {
  386.             if (gPrintPage == 1) teOffset = 0;
  387.             te = (*frHndl)->doc.message[kMessageOut];
  388.             InsetRect(&theInk, 4, 4);
  389.             CTEPrint(te, &teOffset, &theInk);
  390.             if (teOffset == -1) gPrintPage = 0;
  391.             return;
  392.         }
  393.         if (curPort->portBits.rowBytes & 0x8000)
  394.             RectRgn(colorRgn = NewRgn(), &theInk);
  395.                 /* Print the board in grayscale or color if user has so chosen. */
  396.     }
  397.     else {
  398.         SetRectRgn(curPort->clipRgn, -30000, -30000, 30000, 30000);
  399.  
  400.         if (!messageDoc) {
  401.             if (!gPrintPage) ImageBoardLines(8, hOffset, vOffset);
  402.  
  403.             colorRgn = ScreenDepthRegion(8);        /* Screen of 8-bit or greater get color icon. */
  404.             pt.h = pt.v = 0;
  405.             GlobalToLocal(&pt);
  406.             OffsetRgn(colorRgn, pt.h, pt.v);        /* Localize the area that gets color icons. */
  407.  
  408.             if (!gPrintPage) SetLayerWorld(gBoardLayer);
  409.         }
  410.     }
  411.  
  412.     if (!colorRgn) colorRgn = NewRgn();
  413.     if (!testRgn)  testRgn  = NewRgn();
  414.  
  415.     if (!gLastColorRgn) gLastColorRgn = NewRgn();
  416.     if ((gPrintPage) || (!EqualRgn(colorRgn, gLastColorRgn)))
  417.         for (i = 0; i < 120; ++i) gLastPiece[i] = 0;
  418.             /* If printing, exporting a board, or if color region has changed, redraw all squares. */
  419.     CopyRgn(colorRgn, gLastColorRgn);
  420.  
  421.     invertBoard = (*frHndl)->doc.invertBoard;
  422.     lastFrom = lastTo = 0;
  423.     gameIndex = (*frHndl)->doc.gameIndex;
  424.     gameMoves = (*frHndl)->doc.gameMoves;
  425.     if (gameIndex) {
  426.         lastFrom = (**gameMoves)[gameIndex - 1].moveFrom;
  427.         lastTo   = (**gameMoves)[gameIndex - 1].moveTo;
  428.         if (!lastFrom) {
  429.             if (gameIndex > 1) {
  430.                 lastFrom = (**gameMoves)[gameIndex - 2].moveFrom;
  431.                 lastTo   = (**gameMoves)[gameIndex - 2].moveTo;
  432.             }
  433.         }
  434.     }
  435.  
  436.     if (gPrintPage < 2) {        /* If not printing, or printing first page... */
  437.         if (!messageDoc) {
  438.             for (r = 0; r < 8; ++r) {
  439.                 if (gClearSquare) r = (gClearSquare - START_IBNDS) / 10;
  440.  
  441.                 for (c = 0; c < 8; ++c) {
  442.                     if (gClearSquare) c = gClearSquare - START_IBNDS - 10 * r;
  443.                 
  444.                     piece = (*frHndl)->doc.theBoard[square = START_IBNDS + 10 * r + c];
  445.                     if (gClearSquare) piece = EMPTY;
  446.                     if (piece < WK) piece += KSIDEPIECE;
  447.                     if (piece > BK) piece -= KSIDEPIECE;
  448.                     pieceIconID = piece + KING;
  449.     
  450.                     rr = r;
  451.                     cc = c;
  452.                     if (invertBoard) {
  453.                         rr = 7 - r;
  454.                         cc = 7 - c;
  455.                     }
  456.                     ss = START_IBNDS + 10 * rr + cc;
  457.  
  458.                     if ((rr + cc) & 0x01) pieceIconID += 13;
  459.  
  460.                     if (!gPieceCIcon[pieceIconID])
  461.                         gPieceCIcon[pieceIconID] = ReadCIcon(pieceIconID + 257);
  462.  
  463.                     sqRect.top    = vOffset + kBoardSqSize * rr + 1;
  464.                     sqRect.left   = hOffset + kBoardSqSize * cc + 1;
  465.                     sqRect.bottom = sqRect.top  + 32;
  466.                     sqRect.right  = sqRect.left + 32;
  467.  
  468.                     if (gLastPiece[ss] != pieceIconID + 257) {
  469.                         gLastPiece[ss] = pieceIconID + 257;
  470.                         if (!RectInRgn(&sqRect, colorRgn))        /* If 1-bit, draw b/w icon. */
  471.                             DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 1, false);
  472.                         else {        /* Draw some combo of color and b/w icon. */
  473.                             RectRgn(testRgn, &sqRect);
  474.                             SectRgn(testRgn, colorRgn, testRgn);
  475.                             for (;;) {
  476.                                 if ((*testRgn)->rgnSize == 10) {
  477.                                     if (EqualRect(&((*testRgn)->rgnBBox), &sqRect)) {
  478.                                         DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 8, false);
  479.                                         break;            /* Icon completely on color monitor. */
  480.                                     }
  481.                                 }
  482.                                 DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 1, false);
  483.                                     /* Icon is across two monitors, so first draw it b/w. */
  484.                                 SetClip(testRgn);
  485.                                 DrawCIconByDepth(gPieceCIcon[pieceIconID], sqRect, 8, false);
  486.                                     /* Then redraw the color portion. */
  487.                                 SetRectRgn(testRgn, -30000, -30000, 30000, 30000);
  488.                                 SetClip(testRgn);
  489.                                 break;
  490.                             }
  491.                         }
  492.                     }
  493.  
  494.                     if (!gPrintPage) {
  495.                         if ((square == lastFrom) || (square == lastTo)) {
  496.                             FrameRect(&sqRect);
  497.                             gLastPiece[ss] = 0;
  498.                         }
  499.                     }
  500.  
  501.                     if (gClearSquare) break;
  502.                 }
  503.                 if (gClearSquare) break;
  504.             }
  505.         }
  506.     }
  507.  
  508.     DisposeRgn(colorRgn);
  509.     DisposeRgn(testRgn);
  510.  
  511.     if (!gPrintPage) {
  512.         if (!messageDoc)
  513.             if (!gPrintPage)
  514.                 ResetLayerWorld(gBoardLayer);
  515.         if (toWindow) {
  516.             if (!gClearSquare) {
  517.                 if (!messageDoc) {
  518.                     if (!NewLayer(&windowLayer, nil, nil, curPort, 8, 0)) {
  519.                         InsertLayer(gBoardLayer, windowLayer, 1);
  520.                         boardRect = BoardRect();
  521.                         (*windowLayer)->dstRect = boardRect;
  522.                         InvalLayer(windowLayer, boardRect, false);
  523.                         UpdateLayer(windowLayer);
  524.                         DisposeLayer(windowLayer);
  525.                     }
  526.                 }
  527.             }
  528.         }
  529.     }            
  530.  
  531.     if (gPrintPage) {                /* If printing... */
  532.         if (gPrintPage == 1)        /* If printing page 1... */
  533.             ImageBoardLines(1, hOffset, vOffset);
  534.         ImageMoveList(frHndl, theInk, hOffset);
  535.         return;
  536.     }
  537.  
  538.     if (!justBoard) {
  539.         SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  540.         if (!messageDoc) UpdateGameStatus(frHndl);
  541.         DoDrawControls(curPort, false);
  542.         if (!messageDoc) {
  543.             OutlineControl((*frHndl)->doc.sendMessage);
  544.             DrawTime(frHndl);
  545.             DrawPalette(frHndl);
  546.         }
  547.         SetOrigin(0, 0);
  548.     }
  549. }
  550.  
  551.  
  552.  
  553. /*****************************************************************************/
  554.  
  555.  
  556.  
  557. void    ImageMoveList(FileRecHndl frHndl, Rect theInk, short hOffset)
  558. {
  559.     short    gameIndex, numGameMoves, printMoveNum, colsPerPage, colHeight;
  560.     short    pageNum, colNum, colVOffset, numMovePairs, colEndMove, hloc, vloc;
  561.     Str255    pstr;
  562.  
  563.     gameIndex    = (*frHndl)->doc.gameIndex;
  564.     numGameMoves = (*frHndl)->doc.numGameMoves;
  565.     printMoveNum = (*frHndl)->doc.startColor;
  566.     colsPerPage  = (theInk.right  - theInk.left) / 180;
  567.     colHeight    = (theInk.bottom - theInk.top) - 2 * kBoardHOffset;
  568.  
  569.     for (pageNum = 1; pageNum <= gPrintPage; ++pageNum) {
  570.  
  571.         for (colNum = 1; colNum <= colsPerPage; ++colNum) {
  572.  
  573.             hloc = colNum * 180 - 120;
  574.  
  575.             colVOffset = 0;
  576.             if (pageNum == 1) {
  577.                 if (colNum == 1) colVOffset = (3 * 20);
  578.                 if (hloc + 130 >= hOffset)
  579.                     for (; colVOffset < (kBoardHeight + 20 + kBoardVOffset); colVOffset += 20) {};
  580.                         /* Start this column below the board on 20-pixel boundary. */
  581.             }
  582.  
  583.             numMovePairs = (colHeight - colVOffset) / 20;
  584.             colEndMove   = printMoveNum + 2 * numMovePairs;
  585.  
  586.             if (pageNum == gPrintPage) {
  587.  
  588.                 if ((pageNum == 1) && (colNum == 1)) {
  589.                     MoveTo(hloc, theInk.top + 20);
  590.                     pcpy(pstr, (*frHndl)->fileState.fss.name);
  591.                     TextFace(bold + underline);
  592.                     DrawString(pstr);
  593.                     TextFace(normal);
  594.                 }
  595.  
  596.                 for (; printMoveNum < colEndMove; ++printMoveNum) {
  597.  
  598.                     RepositionBoard(frHndl, printMoveNum, false);
  599.  
  600.                     if (printMoveNum >= numGameMoves) {
  601.                         gPrintPage = 0;
  602.                         RepositionBoard(frHndl, gameIndex, false);
  603.                         return;
  604.                     }
  605.  
  606.                     vloc = theInk.top + colVOffset + 20;
  607.  
  608.                     if (!(printMoveNum & 0x01)) {
  609.                         pcpydec(pstr, printMoveNum / 2 + 1);
  610.                         MoveTo(hloc - 16 - StringWidth(pstr), vloc);
  611.                         DrawString(pstr);
  612.                         DrawString("\p)");
  613.                         MoveTo(hloc, vloc);
  614.                     }
  615.                     else {
  616.                         MoveTo(hloc + 40, vloc);
  617.                         MoveTo(hloc + 40 + 12, vloc);
  618.                         colVOffset += 20;
  619.                     }
  620.  
  621.                     if (AnnotateMove(frHndl, printMoveNum, gameIndex, pstr))
  622.                         TextFace(underline);
  623.  
  624.                     DrawString(pstr);
  625.                     TextFace(normal);
  626.                 }
  627.             }
  628.  
  629.             if ((printMoveNum = colEndMove) >= numGameMoves) {
  630.                 gPrintPage = 0;
  631.                 RepositionBoard(frHndl, gameIndex, false);
  632.                 return;
  633.             }
  634.         }
  635.     }
  636.  
  637.     RepositionBoard(frHndl, gameIndex, false);
  638. }
  639.  
  640.  
  641.  
  642.